import 'package:dartkit/dartkit.dart';
import 'package:test/test.dart';

/// 每次计时后都等待一段时间，都以tick为计时单位
const Duration tick = Duration(milliseconds: 200);

/// 等待n个tick
Future<void> waitTick([int t = 1]) async {
  if (t <= 0) return;

  for (int i = 0; i < t; i++) {
    await Future.delayed(tick);
  }
}

void main() {
  test("正计时测试", () async {
    // 开始计时，等待1个tick后，检测到时间正好在1tick附近
    final counter = TimeCounter();
    counter.forward();
    await waitTick();
    expect(counter.time.isNear(tick), isTrue);
  });

  test("倒计时测试", () async {
    // 向后计时，等待一个tick后，检测到时间在-tick附近
    final counter = TimeCounter();
    counter.backward();
    await waitTick();
    expect(counter.time.isNear(-tick), isTrue);
  });

  test("运行状态测试", () async {
    // 一开始时，是静止的
    final counter = TimeCounter();
    expect(counter.isRunning, isFalse);
    // 向前运行，变成运行中
    counter.forward();
    expect(counter.isRunning, isTrue);
    // 停止后，又是静止状态
    counter.stop();
    expect(counter.isRunning, isFalse);
    // 向后运行，又变成运行中
    counter.backward();
    expect(counter.isRunning, isTrue);
  });

  test("停止在当下测试", () async {
    // 开始计时1tick后，调用停止功能
    final counter = TimeCounter();
    counter.forward();
    await waitTick();
    counter.stop();
    // 再等待1tick，发现时间依然停留在原处
    final Duration before = counter.time;
    await waitTick();
    final Duration after = counter.time;
    expect(before, after);
  });

  test("正常定点停止", () async {
    // 直接将counter停止在某处，观察到时间恰好相等
    final counter = TimeCounter();
    expect(counter.time, Duration.zero);
    counter.stop(at: tick);
    expect(counter.time, tick);
  });

  test("向前定点停止", () async {
    // 向前运行2刻后，直接在第1刻停止，发现时间也能对上号，并且计时器没有在运行
    final counter = TimeCounter();
    counter.forward();
    await waitTick(2);
    counter.stop(at: tick);
    await waitTick();
    expect(counter.isRunning, isFalse);
    expect(counter.time, tick);
  });

  test("向后定点停止", () async {
    // 同前面的测试，方向相反
    final counter = TimeCounter();
    counter.backward();
    await waitTick(2);
    counter.stop(at: tick);
    await waitTick();
    expect(counter.isRunning, isFalse);
    expect(counter.time, tick);
  });
}
